# -*- coding: utf-8 -*-
from PIL import Image
import tinify
import click
import os

#一个key每个月可压缩500张图片
#申请地址 https://tinypng.com/developers
tinify_api_key = ["M5mwnFQBFhVhbpsC2pNzr4xHQJJYnP2Z", "YQSs0WBgmTF24fDhLP0zVPP7jgN65G3n"];
index_tinify_api_key = 0;

#是否建立备份
is_bakeup = False;

#需求备份时，把压缩文件拷贝到文件夹的名字
backup_name = "img_compress_backup";

tinify.key = tinify_api_key[index_tinify_api_key];

#打印版本号
def version(ctx, param, value):
    if not value or ctx.resilient_parsing:
        return
    print "1.0.0";
    ctx.exit()

#标记建立备份
def tag_make_bakeup(ctx, param, value):
    global is_bakeup;
    is_bakeup = value;

#压缩图片
def compress(input_file_path, output_file_path):
    global index_tinify_api_key;
    try:
        source = tinify.from_file(input_file_path);
    except Exception, msg:
        index_tinify_api_key = index_tinify_api_key + 1;
        if index_tinify_api_key >= len(tinify_api_key):
            print u"api key当月可压缩的图片已经超过上限，请申请更多的api key";
            exit();
        tinify.key = tinify_api_key[index_tinify_api_key];
        return compress(input_file_path, output_file_path);
    output_dir_path = os.path.dirname(output_file_path);
    if not os.path.exists(output_dir_path):
        os.makedirs(output_dir_path);
    
    source.to_file(output_file_path);

#压缩列表中的所有图片，并返回图片压缩前后图片的对应关系
def compress_image_list(image_list, inpath, outpath):
    print u"-----开始压缩图片-----"
    compress_path_info = [];
    global is_bakeup;
    progress = 1;

    for image_file_path in image_list:
        print "{0}/{1} {2}".format(progress, len(image_list), image_file_path);
        input_file_path = image_file_path;
        output_file_path = input_file_path;
        #如果有指定输出路径，则直接把文件输出到指定的输出目录，并且忽略掉备份参数
        if outpath != None:
            output_file_path = input_file_path.replace(inpath, outpath);
        elif is_bakeup:
            output_file_path = os.path.join(os.path.join(inpath, backup_name), input_file_path.replace(inpath+"\\", ""));
        compress(input_file_path, output_file_path);
        compress_path_info.append({"input_path": input_file_path, "output_path": output_file_path});

        progress = progress + 1;
    print u"-----压缩图片完毕-----"
    return compress_path_info;


#验证图片完整性
def check_image(path):
    try:
        image_check = Image.open( path )
        image_check.verify()
    except Exception, msg:
        if os.path.exists(path):
            os.remove(path);
        return False;
    return True;

@click.command()
@click.option("-v", "--version", is_flag = True, callback = version, expose_value = False, is_eager = True)
@click.option("-b", "--backup", is_flag = True, callback = tag_make_bakeup, expose_value = False, is_eager = True)
@click.option("-t", "--target", type = click.Choice(["png", "jpg"]), default = None, help = u"被压缩的图片的格式")
@click.option("-i", "--inpath", type = str, default = None, help = u"需要压缩的图片路径")
@click.option("-o", "--outpath", type = str, default = None, help = u"压缩完成后图片的输出路径")
def main(target, inpath, outpath):
    if outpath != None and outpath.endswith("\\"):
        outpath = outpath[: len(outpath) - 1];

    #获取所有图片
    if inpath == None:
        inpath = os.getcwd();
    temp_image_list = [];
    for dir_path, dirs, files in os.walk(inpath):
        #如果在同一个文件夹进行多次压缩，这里忽略掉程序在在压缩文件夹是的backup文件夹
        if dir_path == inpath and backup_name in dirs:
            dirs = dirs.remove(backup_name);

        for file in files:
            name, extend = os.path.splitext(file);
            extend = extend.lower();
            if extend!=".png" and extend!=".jpg" and extend!="jpeg":
                continue;
            temp_image_list.append(os.path.join(dir_path, file));

    #根据命令筛选出需要压缩的图片
    image_list = [];
    for image_file_path in temp_image_list:
        name, extend = os.path.splitext(image_file_path);
        extend = extend.lower();
        if target=="png" and extend==".png":
            image_list.append(image_file_path);
        elif target=="jpg" and ( extend==".jpg" or extend==".jpeg"):
            image_list.append(image_file_path);
        elif target==None:
            image_list.append(image_file_path);

    if len(image_list) == 0:
        print u"没有需要进行压缩的图片";
        return;

    #压缩图片
    auto_compress_times = 2
    while len(image_list) != 0 and auto_compress_times > 0:
        compress_path_info = compress_image_list(image_list, inpath, outpath);

        #压缩完成图片后，进行一次图片完整性验证，找出所有不完整的图片，标记为失败，重新再压缩一遍
        image_list = [];
        for signal in compress_path_info:
            if not check_image(signal["output_path"]):
                image_list.append(signal["input_path"]);

        if(len(image_list)==0):
            continue;

        auto_compress_times = auto_compress_times - 1;

        if(auto_compress_times==0):
            continue;

        print "\n";
        print u"-----以下图片压缩失败即将重新压缩-----"
        for image_file_path in image_list:
            print image_file_path;
        print "\n";

    if len(image_list) != 0:
        print "\n";
        print u"-----以下图片压缩失败请检查或者进行手工压缩-----"
        for image_file_path in image_list:
            print image_file_path;

if __name__ == '__main__':
    main()
